package base.thread_demo.demo08_03;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 线程打断状态演示
 *
 * Thread..interrupt(); 将运行中的线程打断标识设置为true,如果该线程正处于wait,sleep,join时被打断,那么打断标识被重置为false.
 *  main 线程中调用 t1.interrupt(),属于非当前线程中断它自己, 内部会执行 checkAccess()方法.
 *
 *  非当前线程中断它自己解释: interrupt()方法属于 Thread中定义,如果该方法放在线程任务中调用,待线程被分配到时间片
 *  ,执行线程任务,就属于当前线程中断它自己, 如果是其它线程(如本例中 main线程)通过持有他人线程句柄引用(本例中是 t1)
 *  去调用interrupt()方法,当时间片切换给 main线程运行, main线程代码中通过 t1.interrupt()调用, 就属于非当前线程(main)
 *  中断它自己(t1), 其实 main线程只是负责通知 t1线程(t1你被我main打断过一次), 并不会对 t1线程任务造成啥影响,你 t1可以
 *  根据业务需要,通过 isInterrupted()判断是否需要结束任务.
 *  备注:需要注意的是如果 t1正处于wait,join,sleep 时被 interrupt()了,那么不能根据 isInterrupted()=true来判断,
 *  因为处于这3种阶段的 t1被打断,打断标识被重置为了false,所以 isInterrupted()结果为false.
 *  如何解决被重置问题?
 *  因为wait,join,sleep方法都提供了可能发生 InterruptedException, 所以可以在try...catch异常处理过程中重新设置
 *  打断标识为true,即在catch语句块中调用下当前线程的 interrupt().
 *
 *  还有一点需要注意:Thread..interrupted()方法也是来判断线程是否被中断了,但是这个方法有个副作用,就是最后会将打断标识
 *  设置为false.如果有判断后需要还原线程状态的业务,可以调用该方法.
 *
 */
public class InterruptThreadDemo {
    private static final Logger log = LoggerFactory.getLogger(InterruptThread.class);

    public static void main(String[] args) throws InterruptedException {
        InterruptThread t1 = new InterruptThread("t1");
        t1.start();

        log.info("main-> 线程开始休眠3s......");
        // main 线程在 2s 后，打断正在睡眠中的 t1 线程
        Thread.sleep(2000);
        t1.interrupt();// t1.stop(); 过时了
        Thread.sleep(3000);
        log.info("main检测-> 线程被打断过: {}", t1.isInterrupted());
    }

    static class InterruptThread extends Thread {
        public InterruptThread(String name){
            super(name);
        }

        @Override
        public void run() {
            /**
             * 运行时(非休眠时)被打断, isInterrupted() 返回true
                while (true) {
                    log.info("t1内部检测-> 运行时被打断了?:{}", Thread.currentThread().isInterrupted());
                }
            */
//            System.out.println("2-> "+Thread.currentThread());//2-> Thread[t1,5,main]

            /**
             * sleep时被打断, isInterrupted() 返回false(被重置了状态标识)
             */
            try {
                log.info("t1内部检测-> 开始休眠前被打断了:{}", Thread.currentThread().isInterrupted());
                // 我要休息10秒钟，亲，不要打扰我哦
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                log.info("t1内部检测-> 休眠时被打断了:{}", Thread.currentThread().isInterrupted());
            }
        }
    }
}
